package com.qfoud.edu.dbutils.framwork.core;

import com.qfoud.edu.dbutils.framwork.exception.DbutilsException;
import com.qfoud.edu.dbutils.framwork.result.base.ResultSetHandler;

import javax.sql.DataSource;
import java.sql.*;

/**
 * @author xiaobobo
 * @title: QueryRunner
 * @projectName cd-java-2303-project-parent
 * @description: TODO
 * @date 2023/5/11  9:56
 */
public class QueryRunner {

    //这里维护了数据源
    private DataSource dataSource;

    public QueryRunner(DataSource dataSource){
       this.dataSource=dataSource;
    }

    /**
     * 所有更新实现的方法
     * @param sql
     * @param args
     * @return
     */
    public int update(String sql,Object... args)throws Exception{
        Connection connection = dataSource.getConnection();
        //获取PreparedStatement对象
        PreparedStatement preparedStatement = getPreparedStatement(connection,sql, args);
        //程序执行到这里 说明参数是正确的
        //执行这个SQL语句
        int count = preparedStatement.executeUpdate();
        //这里是可以进行资源关闭的
        preparedStatement.close();
        //关闭连接
        connection.close();
        return count;
    }

    /**
     * 获取PreparedStatement对象
     * @param sql
     * @param args
     * @return
     * @throws SQLException
     * @throws DbutilsException
     */
    private PreparedStatement getPreparedStatement(Connection connection,String sql, Object[] args) throws SQLException, DbutilsException {
        //接下来调用Pre...
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //获取请求参数的元数据
        ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData();
        //获取占位符(?)的个数
        int parameterCount = parameterMetaData.getParameterCount();
        if(args.length!=parameterCount){
            throw new DbutilsException("参数的个数和占位符的个数不匹配");
        }
        //程序执行到这里 说明参数的个数是匹配的
        for (int i = 0; i <parameterCount ; i++) {
            //这里进行参数的设置
            preparedStatement.setObject(i+1,args[i]);
        }
        return preparedStatement;
    }


    /**
     * 所有查询实现的方法
     * @param sql
     * @param resultSetHandler
     * @param args
     * @param <T>
     * @return
     */
    public <T> T query(String sql, ResultSetHandler<T> resultSetHandler,Object... args) throws Exception {
        Connection connection = dataSource.getConnection();
        //获取PreparedStatement对象
        PreparedStatement preparedStatement = getPreparedStatement(connection,sql, args);
        //执行
        ResultSet resultSet = preparedStatement.executeQuery();
        T handler = resultSetHandler.handler(resultSet);
        //这里也需要关闭资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
        return handler;
    }

}
